/* 
 *  Created By: Mike Stevens
 *  Project URL: http://www.codeplex.com/sitesecuritymgmt
 *  License: GNU GPL v2
 *  Copyright (C) 2008 Mike Stevens
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 */
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using System.Web;
using SiteSecurityManagement.Service.SharePoint;
using SiteSecurityManagement.Entities.SecurityTree;

namespace SiteSecurityManagement.Service.SecurityTree
{
    class SecurityTreeNodeUtility
    {
        #region Members
        private bool m_navigationUrl;
        private char m_pathSeperator;

        private const int FILLDEPTHLIMIT = 1;
        #endregion

        #region Constructor/Destructor
        public SecurityTreeNodeUtility(bool navigationUrl,char pathSeperator)
        {
            m_navigationUrl = navigationUrl;
            m_pathSeperator = pathSeperator;
        }

        #endregion

        #region Properties
        #endregion

        #region Methods
        /// <summary>
        /// Adds the dummy node.
        /// </summary>
        /// <param name="node">The parent node.</param>
        private void AddDummyNode(TreeNode node)
        {
            TreeNode dummyNode = new TreeNode("dummy","dummy");
            node.ChildNodes.Add(dummyNode);
        }

        /// <summary>
        /// Fills the tree nodes.
        /// </summary>
        /// <param name="treeView">The tree view.</param>
        public void FillTreeNodes(TreeView treeView)
        {
            SPSite siteCollection=SPContext.Current.Site;
            using (SPWeb site = SPContext.Current.Web)
            {
                FillTreeNodes(siteCollection,site, treeView);
            }
        }

        /// <summary>
        /// Fills the tree nodes recursively from the specified site.
        /// </summary>
        /// <param name="siteCollection">The site collection.</param>
        /// <param name="site">The site.</param>
        /// <param name="treeView">The tree view.</param>
        private void FillTreeNodes(SPSite siteCollection,SPWeb site, TreeView treeView)
        {
            using (SPSiteSecurity siteSec = new SPSiteSecurity(site))
            {
                //Add root
                if (siteSec.DoesUserHavePermission(SPBasePermissions.EnumeratePermissions))
                {
                    bool inherits;
                    
                    if (true ==siteSec.DoesNotInheritSecurity() && true==site.IsRootWeb)
                    {
                        inherits = false;
                    }
                    else
                    {
                        inherits = true;
                    }
                    SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                    TreeNode node = secTreeNode.CreateNewNode(siteCollection, site, inherits, m_navigationUrl);
                    if (true == site.IsRootWeb)
                    {
                        node.ShowCheckBox = false;
                    }
                    treeView.Nodes.Add(node);

                    FillSubSites(site, node);
                    FillLists(site, node);
                }
            }
        }

        /// <summary>
        /// Fills the sub sites.
        /// </summary>
        /// <param name="site">The site.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillSubSites(SPWeb site, TreeNode parentNode)
        {
            SPWebCollection subSites = site.Webs;
            foreach (SPWeb subSite in subSites)
            {
                using (SPSiteSecurity siteSec = new SPSiteSecurity(subSite))
                {
                    if (siteSec.DoesUserHavePermission(SPBasePermissions.EnumeratePermissions))
                    {
                        bool inherits;
                        if (true ==siteSec.DoesNotInheritSecurity())
                        {
                            inherits = false;
                        }
                        else
                        {
                            inherits = true;
                        }
                        SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                        TreeNode node = secTreeNode.CreateNewNode(subSite, inherits, m_navigationUrl);
                        parentNode.ChildNodes.Add(node);

                        if (node.Depth < (parentNode.Depth + FILLDEPTHLIMIT))
                        {
                            FillSubSites(subSite, node);
                            FillLists(subSite, node);
                        }
                        else
                        {
                            if (subSite.Webs.Count > 0 ||
                                subSite.Lists.Count > 0)
                            {
                                AddDummyNode(node);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Fills the lists.
        /// </summary>
        /// <param name="site">The site.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillLists(SPWeb site, TreeNode parentNode)
        {
            SPListCollection lists = site.Lists;
            foreach (SPList list in lists)
            {
                using (SPListSecurity listSec = new SPListSecurity(list))
                {
                    if (listSec.DoesUserHavePermission(HttpContext.Current.User.Identity.Name, SPBasePermissions.EnumeratePermissions))
                    {
                        if (false ==list.Hidden)
                        {
                            bool inherits;
                            if (true ==listSec.DoesNotInheritSecurity() && true ==site.IsRootWeb)
                            {
                                inherits = false;
                            }
                            else
                            {
                                inherits = true;
                            }
                            SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                            TreeNode node = new TreeNode();
                            if (list is SPDocumentLibrary)
                            {
                                node = secTreeNode.CreateNewNode((SPDocumentLibrary)list, inherits, m_navigationUrl);
                            }
                            else
                            {
                                node = secTreeNode.CreateNewNode(list, inherits, m_navigationUrl);
                            }
                            parentNode.ChildNodes.Add(node);

                            if (node.Depth < (parentNode.Depth + FILLDEPTHLIMIT))
                            {
                                if (list is SPDocumentLibrary)
                                {
                                    FillFolders(list, node);
                                    FillFiles(list.RootFolder, node);
                                }
                                else
                                {
                                    FillListItems(list, node);
                                }
                            }
                            else
                            {
                                if (list.Items.Count > 0)
                                {
                                    AddDummyNode(node);
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Fills the folders.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillFolders(SPList list, TreeNode parentNode)
        {
            SPFolderCollection folders = list.ParentWeb.GetFolder(list.Title).SubFolders;
            if (null != folders)
            {
                foreach (SPFolder folder in folders)
                {
                    if (folder.Name != "Forms")
                    {
                        using (SPFolderSecurity folderSec = new SPFolderSecurity(folder))
                        {
                            if (folderSec.DoesUserHavePermission(HttpContext.Current.User.Identity.Name, SPBasePermissions.EnumeratePermissions))
                            {
                                bool inherits;
                                if (true ==folderSec.DoesNotInheritSecurity())
                                {
                                    inherits = false;
                                }
                                else
                                {
                                    inherits = true;
                                }

                                SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                                TreeNode node = secTreeNode.CreateNewNode(folder, inherits, m_navigationUrl);
                                parentNode.ChildNodes.Add(node);

                                if (node.Depth < (parentNode.Depth + FILLDEPTHLIMIT))
                                {
                                    FillSubFolders(folder, node);
                                    FillFiles(folder, node);
                                }
                                else
                                {
                                    if (folder.Files.Count > 0 || folder.SubFolders.Count > 0)
                                    {
                                        AddDummyNode(node);
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }


        /// <summary>
        /// Fills the sub folders.
        /// </summary>
        /// <param name="folder">The folder.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillSubFolders(SPFolder folder, TreeNode parentNode)
        {
            SPFolderCollection subFolders = folder.SubFolders;
            foreach (SPFolder subFolder in subFolders)
            {
                using (SPFolderSecurity folderSec = new SPFolderSecurity(subFolder))
                {
                    if (folderSec.DoesUserHavePermission(HttpContext.Current.User.Identity.Name, SPBasePermissions.EnumeratePermissions))
                    {
                        bool inherits;
                        if (true ==folderSec.DoesNotInheritSecurity())
                        {
                            inherits = false;
                        }
                        else
                        {
                            inherits = true;
                        }

                        SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                        TreeNode node = secTreeNode.CreateNewNode(subFolder, inherits, m_navigationUrl);
                        parentNode.ChildNodes.Add(node);

                        if (node.Depth < (parentNode.Depth + FILLDEPTHLIMIT))
                        {
                            FillSubFolders(subFolder, node);
                            FillFiles(folder, node);
                        }
                        else
                        {
                            if (subFolder.SubFolders.Count > 0 ||
                                subFolder.Files.Count > 0)
                            {
                                AddDummyNode(node);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Fills the list items.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillListItems(SPList list, TreeNode parentNode)
        {
            SPListItemCollection listItems = list.Items;

            foreach (SPListItem listItem in listItems)
            {
                using (SPListItemSecurity listItemSec = new SPListItemSecurity(listItem))
                {
                    if (listItemSec.DoesUserHavePermission(HttpContext.Current.User.Identity.Name, SPBasePermissions.EnumeratePermissions))
                    {
                        bool inherits;
                        if (true ==listItemSec.DoesNotInheritSecurity())
                        {
                            inherits = false;
                        }
                        else
                        {
                            inherits = true;
                        }

                        SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                        TreeNode node = secTreeNode.CreateNewNode(listItem, inherits, m_navigationUrl);
                        parentNode.ChildNodes.Add(node);
                    }
                }
            }
        }

        /// <summary>
        /// Fills the files.
        /// </summary>
        /// <param name="folder">The folder.</param>
        /// <param name="parentNode">The parent node.</param>
        private void FillFiles(SPFolder folder, TreeNode parentNode)
        {
            SPFileCollection files = folder.Files;
            foreach (SPFile file in files)
            {
                using (SPFileSecurity fileSec = new SPFileSecurity(file))
                {
                    if (fileSec.DoesUserHavePermission(HttpContext.Current.User.Identity.Name, SPBasePermissions.EnumeratePermissions))
                    {
                        bool inherits;
                        if (true ==fileSec.DoesNotInheritSecurity())
                        {
                            inherits = false;
                        }
                        else
                        {
                            inherits = true;
                        }

                        SecurityTreeNode secTreeNode = new SecurityTreeNode(m_pathSeperator);
                        TreeNode node = secTreeNode.CreateNewNode(file, inherits, m_navigationUrl);
                        parentNode.ChildNodes.Add(node);
                    }
                }
            }
        }

        /// <summary>
        /// Fills the child nodes of the specified parent node.
        /// </summary>
        /// <param name="node">The node.</param>
        public void FillChildNodes(TreeNode node)
        {
            SecurityTreeUtility secTreeUtil = new SecurityTreeUtility(node, m_pathSeperator);
            SecurityTreeNodeTypes spObjectType = secTreeUtil.GetObjectType();

            switch (spObjectType)
            {

                case SecurityTreeNodeTypes.SPFolder:
                    {
                        //remove the dummy node
                        node.ChildNodes.RemoveAt(0);

                        SPFolder folder = secTreeUtil.GetFolder();
                        FillSubFolders(folder, node);
                        FillFiles(folder, node);
                        break;
                    }
                case SecurityTreeNodeTypes.SPDocumentLibrary:
                    {
                        //remove the dummy node
                        node.ChildNodes.RemoveAt(0);

                        SPDocumentLibrary docLib = secTreeUtil.GetDocumentLibrary();
                        FillFolders(docLib, node);
                        FillFiles(docLib.RootFolder, node);
                        break;
                    }
                case SecurityTreeNodeTypes.SPList:
                    {
                        //remove the dummy node
                        node.ChildNodes.RemoveAt(0);

                        SPList list = secTreeUtil.GetList();
                        FillListItems(list, node);
                        break;
                    }
                case SecurityTreeNodeTypes.SPWeb:
                    {
                        using (SPWeb site = secTreeUtil.GetSite())
                        {
                            if (false ==site.IsRootWeb)
                            {
                                //remove the dummy node
                                node.ChildNodes.RemoveAt(0);

                                FillSubSites(site, node);
                                FillLists(site, node);
                            }
                        }
                        break;
                    }
            }
        }
        #endregion


    }
}
